﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using Microsoft.VisualStudio.Modeling;
using VsxFactory.Modeling.Strategies.Rules;

namespace VsxFactory.Modeling.Strategies
{
    public interface IFilter
    {
        bool Execute(IStrategyContext ctx, GenerationSpec wrapper);
    }

    public class CheckBinary : IFilter
    {
        [DefaultValue(null)]
        public IFilter Left { get; set; }
        [DefaultValue(null)]
        public IFilter Right { get; set; }
        [DefaultValue("AND")]
        public string Operator { get; set; }

        public CheckBinary()
        {
            Operator = "AND";
        }

        public bool Execute(IStrategyContext ctx, GenerationSpec wrapper)
        {
            if (Operator != "AND" && Operator != "OR")
                throw new Exception("Invalid operator (must be AND or OR)");
            var result = Left.Execute(ctx, wrapper);
            if (result == false && Operator == "AND")
                return false;
            if (result == true && Operator == "OR")
                return true;
            return Right.Execute(ctx, wrapper);
        }
    }

    public class CheckExpression : IFilter
    {
        private Func<IStrategyContext, GenerationSpec, bool> action;

        public CheckExpression(Func<IStrategyContext, GenerationSpec, bool> action)
        {
            System.Diagnostics.Contracts.Contract.Requires(action != null);

            this.action = action;
        }

        public bool Execute(IStrategyContext ctx, GenerationSpec wrapper)
        {
            return action(ctx, wrapper);
        }
    }

    public class CheckElement : PathFilter, IFilter
    {
        public bool Execute(IStrategyContext ctx, GenerationSpec wrapper)
        {
            Tuple<GenerationSpec, DomainPropertyInfo> result;
            return CheckPath(ctx, wrapper, out result);
        }
    }
}
